_package("alz.core");

_class("EventTarget", "", function(){
	this._init = function(){
		_super._init.call(this);
		this._parent = null;
		/* *
		 * 所有的事件响应函数都不与组件对象绑定，而是存储在这个映射表中
		 * [注意]不能将该属性放到原型属性里面去，不然两个对象会共享之
		 * {obj:o,cbid:n,wrap:f}
		 */
		this._listeners = {};  //事件映射表  //{事件监听器列表}
	};
	this.dispose = function(){
		for(var k in this._listeners){
			var arr = this._listeners[k];
			for(var i = 0, len = arr.length; i < len; i++){
				arr[i] = null;
			}
			//arr = null;
			delete this._listeners[k];
		}
		this._parent = null;
		_super.dispose.apply(this);
	};
	this.getParent = function(){
		return this._parent;
	};
	this.setParent = function(v){
		this._parent = v;
	};
	/* *
	 * 添加一个事件监听对象(数据变化事件)
	 * @param listener {Component} 实现了onXXXX 接口的组件
	 * /
	this.addEventListener = function(type, listener){
		this._listeners.push(listener);
	};
	this.removeEventListener = function(type, listener){
		this._listeners.removeAt(this._listeners.indexOf(listener));
	};
	*/
	/**
	 * 此方法允许在事件目标上注册事件侦听器。
	 * @java void addEventListener(String type, EventListener listener, boolean useCapture);
	 * [TODO]检查type的合法值
	 * [TODO]同一个事件响应函数不应该被绑定两次
	 * @param {String} type 事件类型
	 * @param {Object} listener 事件监听者{obj,cbid,wrap}
	 * @param {Boolean} useCapture
	 */
	this.addEventListener = function(type, listener, useCapture){
		/*
		if(typeof listener["on" + type.capitalize()] != "function"){
			runtime.warning("[EventTarget::addEventListener]缺少事件" + type);
			//throw "[EventTarget::addEventListener]error";
		}
		*/
		if(!this._listeners[type]){
			this._listeners[type] = [];  //[TODO]使用{}来模拟多个事件执行顺序的无关性
		}/*else{
			runtime.error("[EventTarget::addEventListener]" + this._listeners[type].length);
		}*/
		this._listeners[type].push(listener);
	};
	/**
	 * 移除事件监听
	 * @param {String} type 事件类型
	 * @param {Component} listener 事件监听组件
	 * @param {Boolean} useCapture
	 */
	this.removeEventListener = function(type, listener, useCapture){
		if(this._listeners[type]){
			var arr = this._listeners[type];
			for(var i = 0, len = arr.length; i < len; i++){
				var item = arr[i];
				for(var k in item){
					item[k] = null;
				}
				arr[i] = null;
				arr.removeAt(i, 1);  //移除元素
				if(item === listener){
					break;
				}
				//默认移除所有事件
			}
		}
	};
	/**
	 * 分派事件(属性变化)
	 * @param ev {EventBase}
	 */
	this.dispatchEvent = function(ev){
		var map = this._listeners[ev.getType()];
		if(map){  //检查事件映射表中是否有对应的事件
			for(var i = 0, len = map.length; i < len; i++){
				/*
				var o = map[i];
				var k = "on" + ev.getType().capitalize();
				var f = o[k];
				if(k in o && typeof f == "function"){
					//[TODO]针对dataChange可能存在未释放的脚本对象
					if(!runtime.getConfData("core_shield")){
						f.call(o, ev);
					}else{
						try{
							f.call(o, ev);
							//f.apply(o, arguments);
						}catch(ex){  //屏蔽某个事件的报错
							runtime.error("[EventTarget::dispatchEvent]" + ex.message);
						}
					}
				}
				*/
				map[i].wrap.call(null, ev);
			}
		}
		ev.dispose();  //析构事件对象
		map = null;
	};
	/*
	/ **
	 * 添加一个数据监听对象
	 * @param listener {FolderListView} 实现了onDateChange接口的视图组件
	 * /
	this.addDataListener = function(listener){
		if(typeof listener.onDataChange != "function"){
			runtime.error("[MetaTable::addDataListener]listener(" + listener.getClassName() + ")未实现onDataChange接口");
			return;
		}
		this._listeners.push(listener);
	};
	this.removeDataListener = function(listener){
		this._listeners.removeAt(this._listeners.indexOf(listener));
	};
	*/
	var MAP_EVENTS = {
		"activate"        : "Activate",
		"afterprint"      : "AfterPrint",
		"afterupdate"     : "AfterUpdate",
		"beforeactivate"  : "BeforeActivate",
		"beforecopy"      : "BeforeCopy",
		"beforecut"       : "BeforeCut",
		"beforedeactivate": "BeforeDeactivate",
		"beforeeditfocus" : "BeforeEditFocus",
		"beforepaste"     : "BeforePaste",
		"beforeprint"     : "BeforePrint",
		"beforeunload"    : "BeforeUnload",
		"beforeupdate"    : "BeforeUpdate",
		"blur"            : "Blur",
		"cellchange"      : "CellChange",
		"click"           : "Click",
		"contextmenu"     : "ContextMenu",
		"controlselect"   : "ControlSelect",
		"copy"            : "Copy",
		"cut"             : "Cut",
		"dataavailable"   : "DataAvailable",
		"datasetchanged"  : "DatasetChanged",
		"datasetcomplete" : "DatasetComplete",
		"dblclick"        : "DblClick",
		"deactivate"      : "Deactivate",
		"drag"            : "Drag",
		"dragend"         : "DragEnd",
		"dragenter"       : "DragEnter",
		"dragleave"       : "DragLeave",
		"dragover"        : "DragOver",
		"dragstart"       : "DragStart",
		"drop"            : "Drop",
		"errorupdate"     : "ErrorUpdate",
		"filterchange"    : "FilterChange",
		"focus"           : "Focus",
		"focusin"         : "FocusIn",
		"focusout"        : "FocusOut",
		"help"            : "Help",
		"keydown"         : "KeyDown",
		"keypress"        : "KeyPress",
		"keyup"           : "KeyUp",
		"layoutcomplete"  : "LayoutComplete",
		"load"            : "Load",
		"losecapture"     : "LoseCapture",
		"mousedown"       : "MouseDown",
		"mouseenter"      : "MouseEnter",
		"mouseleave"      : "MouseLeave",
		"mousemove"       : "MouseMove",
		"mouseout"        : "MouseOut",
		"mouseover"       : "MouseOver",
		"mouseup"         : "MouseUp",
		"mousewheel"      : "MouseWheel",
		"move"            : "Move",
		"moveend"         : "MoveEnd",
		"movestart"       : "MoveStart",
		"page"            : "Page",
		"paste"           : "Paste",
		"propertychange"  : "PropertyChange",
		"readystatechange": "ReadyStateChange",
		"resize"          : "Resize",
		"resizeend"       : "ResizeEnd",
		"resizestart"     : "ResizeStart",
		"rowenter"        : "RowEnter",
		"rowexit"         : "RowExit",
		"rowsdelete"      : "RowsDelete",
		"rowsinserted"    : "RowsInserted",
		"scroll"          : "Scroll",
		"select"          : "Select",
		"selectstart"     : "SelectStart",
		"unload"          : "Unload",

		"scrollstart"     : "ScrollStart",
		"scrollend"       : "ScrollEnd"
	};
	this.fireEvent = function(ev, argv){
		var type;
		if(typeof ev == "string"){
			type = ev;
			ev = argv;
			argv = arguments[2];
		}else{
			type = ev.type;
		}
		/*
		type = type.replace(/^(mouse|key)([a-z])/i, function(_0, _1, _2){
			return _1.capitalize() + _2.capitalize();
		});
		*/
		type = type in MAP_EVENTS ? MAP_EVENTS[type] : type.capitalize();
		var name = "on" + type;
		if(typeof this[name] == "function"){
			//runtime.log("[" + this._className + "::fireEvent]type=" + type);
			if(runtime.getConfData("core_shield")){
				try{
					switch(arguments.length){
					case 1: return this[name](ev);
					case 2: return this[name].apply(this, [ev].concat(argv));
					case 3: return this[name].apply(this, arguments);
					}
				}catch(ex){  //屏蔽事件中的错误
					//return false;
				}
			}else{
				switch(arguments.length){
				case 1: return this[name](ev);
				case 2: return this[name].apply(this, [ev].concat(argv));
				case 3: return this[name].apply(this, arguments);
				}
			}
		}else{
			//runtime.log("[" + this._className + "::fireEvent]failure(type=" + type + ")");
			//return false;
		}
	};
});